package org.bud.rung.bit.cron;

import java.time.LocalDateTime;
import java.util.function.Supplier;

/**
 * @author shaun
 * @date 2024/8/11
 * @instruction
 */
public abstract class CronTimeBase implements CronItem {
    protected LocalDateTime last;
    protected CronType type;
    protected boolean initial;
    protected Integer next;
    protected boolean isAdder;
    protected boolean preAdder;
    protected boolean preStop;
    protected boolean modify;

    @Override
    public void init(LocalDateTime preDateTime,boolean initial) {
        this.last = preDateTime;
        this.initial = initial;
    }

    @Override
    public void type(Supplier<CronType> typsSup,String cron) {
        this.type = typsSup.get();
        this.type.init(cron);
    }

    @Override
    public void reset(boolean preAdder,boolean preStop) {
        this.preAdder = preAdder;
        this.preStop = preStop;
        this.isAdder = false;
        this.modify = false;
    }

    protected abstract void initialNext();

    @Override
    public Integer next() {
        initialNext();
        if(lastAdder()){
            this.isAdder = this.type.isAdder();
        }

        if(initial){
            int temp = this.next;
            if(!lastItem()){
                this.next = this.type.start();
            }
            this.modify = this.next != temp;
        }

        if(!initial && !preStop){
            if(preAdder || !initial ){
                this.next += this.type.step();
                this.modify = true;
            }
            if(checkNext()){
                this.isAdder = true;
                this.next = this.type.start();
            }
        }
        return this.next;
    }

    @Override
    public boolean checkNext() {
        return true;
    }

    @Override
    public boolean toAdder() {
        return this.isAdder;
    }

    @Override
    public boolean isStop() {
        return !this.isAdder;
    }

    @Override
    public boolean initial() {
        return this.initial;
    }

    protected abstract LocalDateTime with();

    @Override
    public LocalDateTime last() {
        if(this.modify){
            return with();
        }
        return last;
    }

    @Override
    public CronType getType() {
        return this.type;
    }

    private boolean lastItem(){
        return this.type instanceof CronStar;
    }

    private boolean lastAdder(){
        return this.preAdder || this.type instanceof CronDigit;
    }
}
